import { OnDestroy } from '@angular/core';
import { IContext } from '../model/context.interface';
import { Observable } from 'rxjs/Observable';
import { Subscription, ISubscription } from 'rxjs/Subscription';
import { Subject } from 'rxjs/Subject';
import { IContextBroker } from './context-broker.interface';
import { Observer } from 'rxjs/Observer';

export class AppContextBroker implements IContextBroker, OnDestroy {
    private _observersByContextName: Map<string, any> = new Map<string, any>();

    constructor() { }

    registerProvider(context: IContext): void {
        const subject = this._observersByContextName.get(context.contextClass);
        if (subject != null) {
            subject.next(context);
        }
    }

    registerObservableProvider<T extends IContext>(contextClass: string, contextProvider: Observable<T>): Subscription {
        return contextProvider.subscribe((context: T) => {
            const subject = this._observersByContextName.get(contextClass);
            if (subject != null) {
                subject.next(context);
            }
        });
    }

    registerListener<T extends IContext>(contextClass: string, contextObserver: Observer<T>): Subscription {
        let subject: Subject<T> = this._observersByContextName.get(contextClass);
        if (subject == null) {
            subject = new Subject<T>();
            this._observersByContextName.set(contextClass, subject);
        }

        return subject.subscribe(contextObserver);
    }


    registerContextListner<T extends IContext>(contextClass: string): Observable<T> {
        let subject: Subject<T> = this._observersByContextName.get(contextClass);
        if (subject == null) {
            subject = new Subject<T>();
            this._observersByContextName.set(contextClass, subject);
        }
        return subject as Observable<T>;
    }

    cancelSubscription(subscription: Subscription, requestId?: string): void {
        if (!subscription)
            return;

        subscription.unsubscribe();
    }

    ngOnDestroy() {
        if (this._observersByContextName) {
            this._observersByContextName.forEach(item => {
                (<ISubscription>item).unsubscribe();
            });
            this._observersByContextName.clear();
        }
    }
}